"""
Case Type   : 系统内部使用工具
Case Name   : 开启RTO后执行备机减容
Create At   : 2022/03/03
Owner       : opentestcase018
Description :
    1.开启RTO并配置相关参数
    2.执行备机减容
    3.清理环境
    gs_uninstall 删除数据库：gs_uninstall --delete-data
    关闭RTO并恢复相关参数
    清理用户下进程
    删除数据库相关目录并删除用户
Expect      :
    1.RTO开启且参数配置成功
    2.备机减容成功
    3.清理成功
History     :
    2022-6-06 opentestcase039 优化用例，根据自动化连跑要求，改为在源库上操作
    2022-7-01 opentestcase039 优化用例，增加检查gs_sshexkey工具步骤
    2022-8-03 opentestcase039 优化用例，增加检查stand_name后断言
"""
import os
import unittest
from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro
COMMONSH = CommonSH("PrimaryDbUser")
Constant = Constant()


@unittest.skipIf(3 != COMMONSH.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.primary_root_node = Node('PrimaryRoot')
        self.primary_node = Node('PrimaryDbUser')
        self.standby1_root_node = Node('Standby1Root')
        self.standby1_node = Node('Standby1DbUser')
        self.standby2_root_node = Node('Standby2Root')
        self.standby2_node = Node('Standby2DbUser')
        self.com_root = CommonSH("PrimaryRoot")
        self.com_user = CommonSH("PrimaryDbUser")
        self.s_com1 = CommonSH("Standby1DbUser")
        self.s_com2 = CommonSH("Standby2DbUser")
        self.u_name = self.primary_node.ssh_user
        self.ssh_file = os.path.join('/home', self.u_name, 'hostfile')
        num = COMMONSH.get_node_num()
        self.assertGreaterEqual(num, 3, "执行失败:节点数量异常，减容不执行")
        self.log.info("查询synchronous_standby_names默认值")
        result = COMMONSH.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"primary synchronous_standby_names is {result}")
        self.synchronous_standby_names_p = result.strip().splitlines()[-2]
        result = self.s_com1.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"s1 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s1 = result.strip().splitlines()[-2]
        result = self.s_com2.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"s2 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s2 = result.strip().splitlines()[-2]

        self.host_tuple = (self.primary_node.ssh_host,
                           self.standby1_node.ssh_host,
                           self.standby2_node.ssh_host)
        self.params = {'-f': 'test_hosts'}

    def test_gs_dropnode(self):
        text = '----step1:开启RTO并配置相关参数 expect:成功----'
        self.log.info(text)
        par_lis = ['recovery_parse_workers=4', 'recovery_redo_workers=4',
                   'hot_standby=off']
        for par in par_lis:
            guc_cmd = f"source {macro.DB_ENV_PATH};" \
                      f"gs_guc set -N all -I all -c '{par}';"
            guc_res = self.primary_node.sh(guc_cmd).result()
            self.log.info(guc_res)
            self.assertIn(Constant.GSGUC_SUCCESS_MSG, guc_res, 'guc执行失败')
        re_cmd = f"source {macro.DB_ENV_PATH};" \
                 f"gs_om -t restart;"
        re_res = self.primary_node.sh(re_cmd).result()
        self.log.info(re_res)
        self.assertIn('Successfully started', re_res, '数据库重启失败')

        text = '----step2:执行备机减容 expect:减容成功----'
        self.log.info(text)
        self.log.info('构建减容命令shell脚本前置条件')
        drop_cmd = f'gs_dropnode -U {self.u_name} -G {self.u_name} ' \
                   f'-h {self.standby1_node.ssh_host}'
        self.log.info(drop_cmd)
        shell_path = os.path.join('/', 'home', f'{self.u_name}', 'dropnode.sh')
        shell_cmd = f'touch {shell_path};echo -e {drop_cmd} > {shell_path};' \
                    f'chmod 755 {shell_path};cat {shell_path}'
        self.log.info(shell_cmd)
        pri_shell_res = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(pri_shell_res)
        self.log.info('对备1执行减容操作')
        drop_cmd = f'''source {macro.DB_ENV_PATH}
                   expect <<EOF
                   set timeout 200
                   spawn {shell_path}
                   expect "(yes/no)?"
                   send "yes\\n"
                   expect eof\n''' + '''EOF'''
        self.log.info(drop_cmd)
        drop_res = self.primary_node.sh(drop_cmd).result()
        self.assertIn('Success to drop the target nodes', drop_res, '减容失败')

        self.log.info('检查数据库是否减容')
        check_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_om -t status --detail;'
        self.log.info(check_cmd)
        check_res = self.primary_node.sh(check_cmd).result()
        self.log.info(check_res)
        self.assertNotIn(self.standby1_node.ssh_host, check_res, '数据库状态检查失败')

    def tearDown(self):
        text = "----step3:卸载数据库，清理用户及文件 expect:成功----"
        self.log.info(text)
        text = '----开启RTO并配置相关参数 expect:成功----'
        self.log.info(text)
        par_lis = ['recovery_parse_workers=1', 'recovery_redo_workers=1',
                   'hot_standby=oN']
        res_lis = []
        for par in par_lis:
            guc_cmd = f"source {macro.DB_ENV_PATH};" \
                      f"gs_guc set -N all -I all -c '{par}';"
            guc_res = self.primary_node.sh(guc_cmd).result()
            self.log.info(guc_res)
            res_lis.append(guc_res)
            self.assertIn(Constant.GSGUC_SUCCESS_MSG, guc_res, 'guc执行失败')
        re_cmd = f"source {macro.DB_ENV_PATH};" \
                 f"gs_om -t restart;"
        re_res = self.primary_node.sh(re_cmd).result()
        self.log.info(re_res)
        self.log.info('-----创建root互信-----')
        result = self.common.get_sh_result(self.primary_root_node,
                                           f"ls {macro.DB_SCRIPT_PATH}")
        if "gs_sshexkey" not in result:
            cmd = f"cd {macro.DB_SCRIPT_PATH}/../; " \
                  f"tar -zxvf openGauss-Package-bak*.tar.gz > /dev/null"
            result = self.primary_root_node.sh(cmd).result()
            self.log.info(result)
            result = self.common.get_sh_result(self.primary_root_node,
                                               f"ls {macro.DB_SCRIPT_PATH}")
            self.log.info(result)
            if "gs_sshexkey" not in result:
                raise Exception("cat not find gs_sshexkey, Please check!")

        self.com_root.exec_gs_sshexkey(macro.DB_SCRIPT_PATH,
                                       *self.host_tuple,
                                       **self.params)
        result = self.com_root.exec_expension(f"{self.primary_node.ssh_user}",
                                              f"{self.primary_node.ssh_user}",
                                              f"{self.standby1_node.ssh_host}",
                                              f"{macro.DB_XML_PATH}")
        self.log.info(result)
        self.log.info("恢复各节点synchronous_standby_names")
        COMMONSH.execute_gsguc("reload",
                               Constant.GSGUC_SUCCESS_MSG,
                               f"synchronous_standby_names="
                               f"'{self.synchronous_standby_names_p}'",
                               single=True)
        self.s_com1.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s1}'",
                                  single=True)
        self.s_com2.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s2}'",
                                  single=True)
        for res in res_lis:
            self.assertIn(Constant.GSGUC_SUCCESS_MSG, res, 'guc执行失败')
        self.assertIn('Successfully started', re_res, '数据库重启失败')
        self.assertTrue(result)
        self.log.info(f'----{os.path.basename(__file__)} finish----')
